﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Text.RegularExpressions;
using System.Windows.Media.Imaging;
using IkeCode.WP7.Toolkit.Core.Enum;
using Microsoft.Phone.Shell;
using XmlLinq = System.Xml.Linq;

namespace IkeCode.WP7.Toolkit
{
    /// <summary>
    /// Tools to help in any cases =)
    /// </summary>
    public static class IcTools
    {
        #region ## Public Methods ##

        /// <summary>
        /// Find a Tile according your page uri
        /// </summary>
        /// <param name="activeTiles">Active tiles enumaration</param>
        /// <param name="pageUri">Tile page uri</param>
        /// <returns>ShellTile or null</returns>
        public static ShellTile FindTile(this IEnumerable<ShellTile> activeTiles, Uri pageUri)
        {
            return activeTiles.FirstOrDefault(x => x.NavigationUri.Equals(pageUri));
        }

        /// <summary>
        /// Add http:// if uri don't contains
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static Uri NormalizeUrl(this Uri url)
        {
            if (!Regex.IsMatch(url.ToString(), "(https|http)+(://)"))
            {
                var newUrl = new Uri(string.Concat("http://", url.ToString()), UriKind.RelativeOrAbsolute);
                return newUrl;
            }
            else
            {
                return url;
            }
        }

        /// <summary>
        /// Try to get image url from string text
        /// </summary>
        /// <param name="text">Source</param>
        /// <returns>Returns first</returns>
        public static Uri TryGetImageUrl(this string text)
        {
            Regex regx = new Regex(@"(http|https)+(://)+([a-zA-Z0-9\\_\\&\\&amp;\\.\\~\\!\\?\\@\\#\\$\\%\\/\\=\\+\\-]*)?.(?:[png|jpeg|jpg|gif|bmp])", RegexOptions.IgnoreCase);
            MatchCollection matches = regx.Matches(text);
            Uri result = null;

            if (matches.Count > 0)
            {
                foreach (Match match in matches)
                {
                    result = new Uri(match.Value, UriKind.Absolute);
                    break;
                }
            }

            return result;
        }

        /// <summary>
        /// Try to get image url from SyndicationItem
        /// </summary>
        /// <param name="item">Source</param>
        /// <returns>Returns first</returns>
        public static Uri TryGetImageUrl(this SyndicationItem item)
        {
            Regex regx = new Regex(@"(http|https)+(://)+([a-zA-Z0-9\\_\\&\\&amp;\\.\\~\\!\\?\\@\\#\\$\\%\\/\\=\\+\\-]*)?.(?:[png|jpeg|jpg|gif|bmp])", RegexOptions.IgnoreCase);
            MatchCollection matches = regx.Matches(item.Summary.Text);
            var hasMatches = matches.Count > 0;
            Uri result = null;
            if (hasMatches)
            {
                foreach (Match match in matches)
                {
                    result = new Uri(match.Value, UriKind.Absolute);
                    break;
                }
            }
            else
            {
                foreach (SyndicationElementExtension ext in item.ElementExtensions)
                {
                    if (ext.GetObject<XmlLinq.XElement>().Name.LocalName == "encoded")
                    {
                        var value = ext.GetObject<XmlLinq.XElement>().Value;
                        MatchCollection matchesSynd = regx.Matches(value);
                        foreach (Match match in matchesSynd)
                        {
                            result = new Uri(match.Value, UriKind.Absolute);
                            break;
                        }
                    }
                }
            }

            return result;
        }

        /// <summary>
        /// Try to get image url from XElement object
        /// </summary>
        /// <param name="element">Source</param>
        /// <returns>Returns first</returns>
        public static string TryGetImageUrl(this XmlLinq.XElement element)
        {
            var text = "";
            if (element != null)
            {
                text = element.ToString().TryGetImageUrl().ToString();
            }
            return text;
        }

        /// <summary>
        /// Try to get youtube url from string text
        /// </summary>
        /// <param name="text">Source</param>
        /// <returns>Returns first</returns>
        public static string TryGetYoutubeUrl(this string text)
        {
            Regex regx = new Regex("http://([\\w+?\\.\\w+])+(youtube|youtu*)+([a-zA-Z\\.]*/)+([a-zA-Z0-9_\\=\\/\\?\\-]*)?", RegexOptions.IgnoreCase);
            MatchCollection matches = regx.Matches(text);
            if (matches.Count > 0)
            {
                text = matches[0].Value;
            }
            else
            {
                text = "";
            }
            return text;
        }

        /// <summary>
        /// Try parse string offset time to DateTime
        /// </summary>
        /// <param name="offset">Offset time</param>
        /// <returns>DateTime</returns>
        public static DateTime TryParse(this string offset)
        {
            return DateTimeOffset.Parse(offset).TryParse();
        }

        /// <summary>
        /// Try parse DateTimeOffset time to DateTime
        /// </summary>
        /// <param name="offset">Offset time</param>
        /// <returns>DateTime</returns>
        public static DateTime TryParse(this DateTimeOffset offset)
        {
            return offset.ToOffset(TimeSpan.Zero).DateTime.ToLocalTime();
        }

        /// <summary>
        /// Return mime type
        /// </summary>
        /// <param name="mimeType">MIME type</param>
        /// <returns></returns>
        public static MimeType GetMimeType(this string mimeType)
        {
            var result = MimeType.Unkown;

            if (mimeType.Equals("image/jpeg"))
                result = MimeType.Jpeg;
            else if (mimeType.Equals("image/gif"))
                result = MimeType.Gif;
            else if (mimeType.Equals("image/bmp"))
                result = MimeType.Bmp;
            else if (mimeType.Equals("image/png"))
                result = MimeType.Png;

            return result;
        }

        /// <summary>
        /// Return MD5 from image uri
        /// </summary>
        /// <param name="imageUrl"></param>
        /// <returns></returns>
        public static string GetImageName(this Uri imageUrl)
        {
            return MD5Core.GetHashString(imageUrl.ToString());
        }

        /// <summary>
        /// Try to get byte array from WriteableBitmap
        /// </summary>
        /// <param name="bmp"></param>
        /// <returns></returns>
        public static byte[] GetBytes(this WriteableBitmap bmp)
        {
            // Init buffer
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
            int[] p = bmp.Pixels;
            int len = p.Length;
            byte[] result = new byte[4 * w * h];

            // Copy pixels to buffer
            for (int i = 0, j = 0; i < len; i++, j += 4)
            {
                int color = p[i];
                result[j + 0] = (byte)(color >> 24); // A
                result[j + 1] = (byte)(color >> 16); // R
                result[j + 2] = (byte)(color >> 8);  // G
                result[j + 3] = (byte)(color);       // B
            }

            return result;
        }

        /// <summary>
        /// Convert BitmapImage to byte array
        /// </summary>
        /// <param name="bitmapImage">BitmapImage</param>
        /// <returns>byte[]</returns>
        public static byte[] GetBytes(this BitmapImage bitmapImage)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                WriteableBitmap btmMap = new WriteableBitmap
                    (bitmapImage.PixelWidth, bitmapImage.PixelHeight);

                // write an image into the stream
                Extensions.SaveJpeg(btmMap, ms,
                    bitmapImage.PixelWidth, bitmapImage.PixelHeight, 0, 100);

                return ms.ToArray();
            }
        }

        #endregion ## Public Methods ##

        #region ## Internal Methods ##



        #endregion ## Internal Methods ##
    }
}
